// *Description*

// Includes
#include "ProjectIncludes.h"

/////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/////////////////////////////////////////// Function Prototypes \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

void initializeDirect3D(HWND hWnd);
void initializeFmod(HWND hWnd);	// Might not need to pass handle?
void cleanDirect3D();

// Process Input
void handleInput();

// Process Data
void updateScene(void);

//JC Process Rendering
bool renderFrame(void);

//JJ Main Game Setup
void mainMenu(void);
void pauseMenu(void);
void overMenu(void);
void helpMenu(void);
void creditMenu(void);
void optionsMenu(void);
void renderHUD(void);
void reset(void);
void copyMap(char* orig, char* dest);

// Map Specific Rendering
void renderMap(IDirect3DSurface9*);

//JC Character Rendering
void renderChars(IDirect3DSurface9*);

//JC Character Initialization
void initPlayer(void);
Character* initEnemy(float x, float y);
Character* initAlly(float x, float y);

//JC Logging
bool initLogs(void);
bool initMainLog(const char* logfile = NULL);
void closeLogs(void);
void closeMainLog(void);
bool initPlayerLog(const char* logfile = NULL);
void closePlayerLog(void);
bool initEnemyLog(const char* logfile = NULL);
void closeEnemyLog(void);
bool initAllyLog(const char* logfile = NULL);
void closeAllyLog(void);

void initCharLists(void);

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

/////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/////////////////////////////////////////////// Entry Point \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

int WINAPI WinMain(HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine,
				   int nCmdShow)
{
	//initLogs(); //JC Disable logs here

	ZeroMemory(&wc, sizeof(WNDCLASSEX));

	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground =(HBRUSH)COLOR_WINDOW;
	wc.lpszClassName = "WindowClass";

	RegisterClassEx(&wc);

	hWnd = CreateWindowEx(NULL,
						  "WindowClass",
						  "Escape from Area 52 - Release Canidate",
						  WS_OVERLAPPEDWINDOW,
						  300, 300,
						  SCREEN_WIDTH, SCREEN_HEIGHT + HUD_HEIGHT,
						  NULL,
						  NULL,
						  hInstance,
						  NULL);

	ShowWindow(hWnd, nCmdShow);

	// Initialize Rand
	srand( (int)time(NULL) );

	// Initialize Direct3D
	initializeDirect3D(hWnd);

	// Initalize Fmod
	initializeFmod(hWnd);
	
	//JC Added to ensure initial map is copied
	copyMap((char*)&lvl1Map, (char*)&cMap);

	//JC Added for GFX Lib testing
	initGraphicsLib();
	initPlayer();
	//initEnemy(21, (SCREEN_HEIGHT - 100));
	//initAlly((SCREEN_WIDTH - 60), 21);

	//initCharLists();

	GFX_LOG << "cMap:\n\n";
	for(int i = 0; i < ROWMAX; ++i) {
		for(int j = 0; j < COLMAX; ++j) {
			GFX_LOG << cMap[i][j];
		}
		GFX_LOG << "\n";
	}
	GFX_LOG << "\n\n";

	// Main Application Loop
	MSG msg;

	//JC Added for animation timer
	LARGE_INTEGER timerFreq;
	QueryPerformanceFrequency(&timerFreq);

	while(TRUE)
	{
		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if(msg.message == WM_QUIT)
			break;

		handleInput();
		updateScene();

		LARGE_INTEGER	frameStart,
						frameEnd;
		QueryPerformanceCounter(&frameStart);
		
		renderFrame();
		
		QueryPerformanceCounter(&frameEnd);
		timerRate = (float)(frameEnd.QuadPart - frameStart.QuadPart) / timerFreq.QuadPart;
		frameCount += timerRate;
	}

	// Clean Up DirectX
	cleanDirect3D();

	//JC Shutdown Graphics Components
	shutdownGraphicsLib();

	//JC Shutdown Main Log
	closeLogs();

	return msg.wParam;
}

// Message Handler for the Application
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		}
		break;
	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}

// Initialize Direct3D
void initializeDirect3D(HWND hWnd)
{
	// Create our d3d interface
	d3d = Direct3DCreate9(D3D_SDK_VERSION);
	
	// A presentation parameter struct
	D3DPRESENT_PARAMETERS d3dpp;

	// Clear it to 0s
	ZeroMemory(&d3dpp, sizeof(d3dpp));

	// Set our display mode to Windowed
	d3dpp.Windowed = TRUE;

	// Discard old frames
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

	// Set the device window to our windowpointer passed as a parameter
	d3dpp.hDeviceWindow = hWnd;

	// Create a device class using this information and the info from the d3dpp struct
	d3d->CreateDevice(D3DADAPTER_DEFAULT,
					  D3DDEVTYPE_HAL,
					  hWnd,
					  D3DCREATE_SOFTWARE_VERTEXPROCESSING,
					  &d3dpp,
					  &d3ddev);

	// Disable VSync
	d3dpp.PresentationInterval = D3DPRESENT_DONOTWAIT;

	//JJ Create Input Objects //
	
	//JJ Create Main Input Object
	DirectInput8Create(wc.hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&m_pInput, 0);

	//JJ Clear Input States
	ZeroMemory(mKeyboardState, sizeof(mKeyboardState));
	ZeroMemory(&mMouseState, sizeof(mMouseState));

	//JJ Create Keyboard and Mouse Input Objects
	m_pInput->CreateDevice(GUID_SysKeyboard, &m_pKeyboard, 0);
	m_pInput->CreateDevice(GUID_SysMouse, &m_pMouse, 0);

	//JJ Set the Data Format
	m_pKeyboard->SetDataFormat(&c_dfDIKeyboard);
	m_pMouse->SetDataFormat(&c_dfDIMouse2);

	//JJ Set Cooperative Level
	m_pKeyboard->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
	m_pMouse->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);

	//JJ Creat a Font Object //

	//JJ Load a font
	//../Fonts/Delicious-Roman.otf
	AddFontResourceEx("../Fonts/Delicious-Roman.otf", FR_PRIVATE, 0);

	//JJ Load D3DXFont, each font style you want to support will need an ID3DXFont
	D3DXCreateFont(d3ddev, 25, 16, FW_BOLD, 0, true, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "../Fonts/Delicious-Roman.otf", &m_pD3DFont);

	D3DXCreateFont(d3ddev, 20, 20, FW_BOLD, 0, true, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "../Fonts/Delicious-Roman.otf", &m_pD3DFont1);

	//JJ Set Game State to MENU
	GameState = MENU;
}

////////////////////////////////////////////////////////////////////////////////MUSIC IS OFF!!!
//JJ Initialize Fmod
void initializeFmod(HWND hWnd)	
{
	//JJ 
	sndVolume = 1.0f;

	result = FMOD::System_Create(&fmodSystem);
	ERRCHECK(result);

	result = fmodSystem->getVersion(&version);
	ERRCHECK(result);

	if(version < FMOD_VERSION)
		printf("ERROR! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION);

	result = fmodSystem->getNumDrivers(&numdrivers);
	ERRCHECK(result);

	if(numdrivers == 0)
	{
		result = fmodSystem->setOutput(FMOD_OUTPUTTYPE_NOSOUND);
		ERRCHECK(result);
	}
	else
	{
		result = fmodSystem->getDriverCaps(0, &caps, 0, 0, &speakermode);
		ERRCHECK(result);

		result = fmodSystem->getSpeakerMode(&speakermode);
		ERRCHECK(result);

		if(caps & FMOD_CAPS_HARDWARE_EMULATED)
		{
			result = fmodSystem->setDSPBufferSize(104, 10);
			ERRCHECK(result);
		}

		result = fmodSystem->getDriverInfo(0, name, 256, 0);
		ERRCHECK(result);

		if(strstr(name, "SigmaTel"))
		{
			result = fmodSystem->setSoftwareFormat(48000, FMOD_SOUND_FORMAT_PCMFLOAT, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
			ERRCHECK(result);
		}
	}

	result = fmodSystem->init(100, FMOD_INIT_NORMAL, 0);
	if(result == FMOD_ERR_OUTPUT_CREATEBUFFER)
	{
		result = fmodSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
		ERRCHECK(result);

		result = fmodSystem->init(100, FMOD_INIT_NORMAL, 0);
		ERRCHECK(result);
	}

	//JJ Initalize Sounds
	result = fmodSystem->createSound("./Sounds/Hurt.wav", FMOD_DEFAULT, 0, &sndPlayerIsHit);
	ERRCHECK(result);

	result = fmodSystem->createSound("./Sounds/Door Open.wav", FMOD_DEFAULT, 0, &sndDoorOpen);
	ERRCHECK(result);

	result = fmodSystem->createSound("./Sounds/Menu Navigation.wav", FMOD_DEFAULT, 0, &sndMenuNav);
	ERRCHECK(result);

	result = fmodSystem->createSound("./Sounds/Pickup.wav", FMOD_DEFAULT, 0, &sndPickup);
	ERRCHECK(result);
	

	result = fmodSystem->createSound("./Sounds/Hurt Enemy.wav", FMOD_DEFAULT, 0, &sndEnemyHurt);
	ERRCHECK(result);


	result = fmodSystem->createSound("./Sounds/Ally Rescue.wav", FMOD_DEFAULT, 0, &sndAllyRescue);
	ERRCHECK(result);


	result = fmodSystem->createSound("./Sounds/Laser_Shoot.wav", FMOD_DEFAULT, 0, &sndFireGun);
	ERRCHECK(result);

	result = fmodSystem->createStream("./Sounds/ZooEscapeGame.MP3", FMOD_LOOP_NORMAL | FMOD_2D | FMOD_HARDWARE, 0, &soundStream);
	ERRCHECK(result);

	//result = fmodSystem->playSound(FMOD_CHANNEL_FREE, soundStream, false, &chMusic);
	//ERRCHECK(result);

	chMusic->setPaused(true);
	chEffects->setPaused(true);
	chTurrets->setPaused(true);
}

// Cleans up Direct3D and releases and RAM\VRAM in use
void cleanDirect3D()
{
	d3ddev->Release();
	d3ddev = NULL;

	d3d->Release();
	d3d = NULL;
}

//JC Input Handling Here
void handleInput() {
	//JC Moved from updateScene()
	//JJ
	//////////////////////////////////////////////////////////////////////////
	// Set Up Input Data
	//////////////////////////////////////////////////////////////////////////

	// Acquire Mouse and Keyboard
	m_pKeyboard->Acquire();
	m_pMouse->Acquire();

	//GetCursorPos(&cursorPos);
	//ScreenToClient(m_hWnd, &cursorPos);

	// Get the State of Keyboard
	HRESULT hr = m_pKeyboard->GetDeviceState(sizeof(mKeyboardState), &mKeyboardState);

	// Check Keyboard State
	if (FAILED(hr))
	{
		// Lost, zero out structure
		ZeroMemory(&mKeyboardState, sizeof(mKeyboardState));

		// Reacquire Keyboard
		m_pKeyboard->Acquire();
	}

	// Get the State of Mouse
	hr = m_pMouse->GetDeviceState(sizeof(DIMOUSESTATE2), (void**)&mMouseState);

	// Check Mouse State
	if (FAILED(hr))
	{
		// Lost, zero out structure
		ZeroMemory(&mMouseState, sizeof(mMouseState));

		// Reacquire Mouse
		m_pMouse->Acquire();
	}

	// Activate Game Sound Channel
	chEffects->setPaused(false);

	switch(GameState)
	{
	case MENU:
		//resetPos = true;

		//JJ If Enter is pressed, start game.
		if(mKeyboardState[DIK_RETURN] & 0x80)
		{
			//GameState = GAME;
			reset();
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_RETURN])
			{
				mKeyboardState[DIK_RETURN] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_RETURN])
			{
				mKeyboardState[DIK_RETURN] = false;
			}
		}


		if(mKeyboardState[DIK_C] & 0x80)
		{
			GameState = CREDIT;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_C])
			{
				mKeyboardState[DIK_C] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_C])
			{
				mKeyboardState[DIK_C] = false;
			}
		}

		if(mKeyboardState[DIK_H] & 0x80)
		{
			GameState = HELP;
			lastState = MENU;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_H])
			{
				mKeyboardState[DIK_H] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_H])
			{
				mKeyboardState[DIK_H] = false;
			}
		}

		if(mKeyboardState[DIK_Q] & 0x80)
		{
			GameState = QUIT;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_Q])
			{
				mKeyboardState[DIK_Q] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_Q])
			{
				mKeyboardState[DIK_Q] = false;
			}
		}

		if(mKeyboardState[DIK_O] & 0x80)
		{
			GameState = OPTIONS;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_O])
			{
				mKeyboardState[DIK_O] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_O])
			{
				mKeyboardState[DIK_O] = false;
			}
		}
		break;

	case GAME:
		//JJ Activate Background Music
		chMusic->setPaused(false);

		//JJ Adjust Player Pos based on Input
		
		// Move Up
		if(mKeyboardState[DIK_UP] & 0x80 && player->velY > -3)
			player->velY -= 1;
		else if(mKeyboardState[DIK_UP] & 0x80 && player->velY < -3)
			player->velY = -3;

		// Move Down
		if(mKeyboardState[DIK_DOWN] & 0x80 && player->velY < 3)	
			player->velY += 1;
		else if(mKeyboardState[DIK_DOWN] & 0x80 && player->velY > 3)
			player->velY = 3;
		
		// No Vertical Input, Null velY
		if(!mKeyboardState[DIK_UP] && !mKeyboardState[DIK_DOWN]) {
			player->velY = 0;
			if((int)player->posY % 5 != 0)
				player->velY = 1;
		}
			
		// Move Left
		if(mKeyboardState[DIK_LEFT] & 0x80 && player->velX > -3)
			player->velX -= 1;
		else if(mKeyboardState[DIK_LEFT] & 0x80 && player->velX < -3)
			player->velX = -3;
		
		// Move Right
		if(mKeyboardState[DIK_RIGHT] & 0x80 && player->velX < 3)	
			player->velX += 1;
		else if(mKeyboardState[DIK_RIGHT] & 0x80 && player->velX > 3)
			player->velX = 3;
		
		// No Horizontal Input, Null vX
		if(!mKeyboardState[DIK_LEFT] && !mKeyboardState[DIK_RIGHT]) {
			player->velX = 0;
			if((int)player->posX % 5 != 0)
				player->velX = 1;
		}

		//JJ Press Esc to Pause Game
		if(mKeyboardState[DIK_ESCAPE] & 0x80)
		{

			GameState = PAUSE;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_ESCAPE])
			{
				mKeyboardState[DIK_ESCAPE] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_ESCAPE])
			{
				mKeyboardState[DIK_ESCAPE] = false;
			}
		}
		
		break;

	case CREDIT:
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////// Credits /////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		//JJ Deactivate Background Music
		chMusic->setPaused(true);

		//JJ Allow Return to Menu

		if(mKeyboardState[DIK_BACK] & 0x80)
		{

			GameState = MENU;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = false;
			}
		}
		break;

	case OVER:
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/////////////////////////////////////////////// Game Over ////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		//JJ Deactivate Background Music
		chMusic->setPaused(true);

		//JJ Pressing Space Restarts the Game
		if(mKeyboardState[DIK_SPACE] & 0x80)
		{
			GameState = RESET;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_SPACE])
			{
				mKeyboardState[DIK_SPACE] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_SPACE])
			{
				mKeyboardState[DIK_SPACE] = false;
			}
		}

		//JJ Pressing Backspace Returns to the Main Menu
		if(mKeyboardState[DIK_BACK] & 0x80)
		{
			GameState = MENU;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = false;
			}
		}

		break;

	case HELP:
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////// Help //////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		//JJ Deactivate Background Music
		chMusic->setPaused(true);

		//JJ Press Backspace to return to the Main Menu
		if(mKeyboardState[DIK_BACK] & 0x80)
		{
			if(lastState == PAUSE)
				GameState = PAUSE;
			else
				GameState = MENU;
			helpPageNum = 0;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			//JJ Delay to return to Pause without returning to Main
			Sleep(400);

			if(!mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = false;
			}
		}

		//JJ Press Right or Left Arrows to return to Change Pages
		if(mKeyboardState[DIK_RIGHT] & 0x80)
		{

			if(helpPageNum >= 1)
			{ helpPageNum = 1; }
			else
			{ helpPageNum++; }
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);
			//JJ Sleep for 1 1/2 secs so can't burn out the sound effect with rapid screen switching
			Sleep(500);

			if(!mKeyboardState[DIK_RIGHT])
			{
				mKeyboardState[DIK_RIGHT] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_RIGHT])
			{
				mKeyboardState[DIK_BACK] = false;
			}
		}

		if(mKeyboardState[DIK_LEFT] & 0x80)
		{

			if(helpPageNum <= 0)
			{ helpPageNum = 0; }
			else
			{ helpPageNum--; }
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);
			//JJ Sleep for 1 1/2 secs
			Sleep(500);

			if(!mKeyboardState[DIK_LEFT])
			{
				mKeyboardState[DIK_LEFT] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_LEFT])
			{
				mKeyboardState[DIK_LEFT] = false;
			}
		}

		break;

	case PAUSE:
		//JJ Deactivate Background Music
		chMusic->setPaused(true);

		//JJ Press Enter to Resume
		if(mKeyboardState[DIK_RETURN] & 0x80)
		{

			GameState = GAME;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_RETURN])
			{
				mKeyboardState[DIK_RETURN] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_RETURN])
			{
				mKeyboardState[DIK_RETURN] = false;
			}
		}

		//JJ Help Guide
		if(mKeyboardState[DIK_H] & 0x80)
		{
			GameState = HELP;
			lastState = PAUSE;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			if(!mKeyboardState[DIK_H])
			{
				mKeyboardState[DIK_H] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_H])
			{
				mKeyboardState[DIK_H] = false;
			}
		}

		//JJ Press Backspace to go back to Main Menu
		if(mKeyboardState[DIK_BACK] & 0x80)
		{

			GameState = MENU;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);
			if(!mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = false;
			}
		}

		//JJ Presentation Cheats
		if(mKeyboardState[DIK_C] & 0x80)
		{
			//Enable cheat mode
			cheater = !cheater;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);
			Sleep(100);
			if(!mKeyboardState[DIK_C])
			{
				mKeyboardState[DIK_C] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_C])
			{
				mKeyboardState[DIK_C] = false;
			}
		}

		if(mKeyboardState[DIK_END] & 0x80)
		{
			//Sets the conditions to move to the next level
			player->posX = 2000.0f;
			player->posY = 2000.0f;
			ifWon = true;

			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);
			//Sleep(500);

			if(!mKeyboardState[DIK_END])
			{
				mKeyboardState[DIK_END] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_END])
			{
				mKeyboardState[DIK_END] = false;
			}
		}

		//JC Added Key Cheats
		if(mKeyboardState[DIK_K] & 0x80)
		{
			player->nKeys += 1;

			if(!mKeyboardState[DIK_END])
			{
				mKeyboardState[DIK_END] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_END])
			{
				mKeyboardState[DIK_END] = false;
			}
		}

		if(mKeyboardState[DIK_M] & 0x80)
		{
			player->mKey = true;
			ifWon = true;

			if(!mKeyboardState[DIK_END])
			{
				mKeyboardState[DIK_END] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_END])
			{
				mKeyboardState[DIK_END] = false;
			}
		}
		break;
		
	case OPTIONS:
		//JJ Deactivate Background Music
		chMusic->setPaused(true);

		//JJ Backspace to go back
		if(mKeyboardState[DIK_BACK] & 0x80)
		{

			GameState = MENU;
			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);
			if(!mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_BACK])
			{
				mKeyboardState[DIK_BACK] = false;
			}
		}

		//JJ +/- to raise or lower volume NOTE: Equals key is actually plus so user doesn't have to hold shift
		if(mKeyboardState[DIK_MINUS] & 0x80)
		{
			if(sndVolume > 0.0f)
			{
				sndVolume -= 0.25f;
				chEffects->setVolume(sndVolume);
				chMusic->setVolume(sndVolume);
				chTurrets->setVolume(sndVolume);
			}

			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			Sleep(500);
			if(!mKeyboardState[DIK_MINUS])
			{
				mKeyboardState[DIK_MINUS] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_MINUS])
			{
				mKeyboardState[DIK_MINUS] = false;
			}
		}

		if(mKeyboardState[DIK_EQUALS] & 0x80)
		{
			if(sndVolume < 1.0f)
			{
				sndVolume += 0.25f;
				chEffects->setVolume(sndVolume);
				chMusic->setVolume(sndVolume);
				chTurrets->setVolume(sndVolume);
			}

			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			Sleep(500);
			if(!mKeyboardState[DIK_EQUALS])
			{
				mKeyboardState[DIK_EQUALS] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_EQUALS])
			{
				mKeyboardState[DIK_EQUALS] = false;
			}
		}

		//JJ Use 'U' & 'M' to unmute or mute sounds.
		if(mKeyboardState[DIK_M] & 0x80)
		{
			// Pause Channels for Adjustment
			chEffects->setPaused(true);

			chEffects->setMute(true);
			chMusic->setMute(true);
			chTurrets->setMute(true);

			chEffects->setPaused(false);

			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			Sleep(500);
			if(!mKeyboardState[DIK_M])
			{
				mKeyboardState[DIK_M] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_M])
			{
				mKeyboardState[DIK_M] = false;
			}
		}

		if(mKeyboardState[DIK_U] & 0x80)
		{
		
			chEffects->setMute(false);
			chMusic->setMute(false);
			chTurrets->setMute(false);

			fmodSystem->playSound(FMOD_CHANNEL_FREE, sndMenuNav, false, &chEffects);

			Sleep(500);
			if(!mKeyboardState[DIK_U])
			{
				mKeyboardState[DIK_U] = true;
			}
		}
		else
		{
			if(mKeyboardState[DIK_U])
			{
				mKeyboardState[DIK_U] = false;
			}
		}
		break;

	case RESET:
		//JJ Resets the Game
		reset();

		chMusic->stop();
		result = fmodSystem->playSound(FMOD_CHANNEL_FREE, soundStream, false, &chMusic);
		ERRCHECK(result);
		chMusic->setPaused(true);
		break;

	case QUIT:
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///////////////////////////////////////////////// Quit ///////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		PostQuitMessage(0);
		break;
	}


}

//JC Process Data Here
void updateScene(void) {
	if(GameState == GAME) {
		player->move();
		//enemy->move();
		//ally->move();
		
		enemy = enemies->first();
		while(enemy != NULL) {
			GFX_LOG << "ENEMY " << enemy->id
					<< " P1(" << enemy->posX << ", " << enemy->posY << ");"
					<< " V(" << enemy->velX << ", " << enemy->velY << ")\n";
			enemy->move();
			GFX_LOG << "\tP2(" << enemy->posX << ", " << enemy->posY << ")\n";
			enemy = enemy->next;
		}

		ally = allies->first();
		while(ally != NULL) {
			GFX_LOG << "ALLY " << ally->id
					<< " P1(" << ally->posX << ", " << ally->posY << ");"
					<< " V(" << ally->velX << ", " << ally->velY << ")\n";
			ally->move();
			GFX_LOG << "\tP2(" << ally->posX << ", " << ally->posY << ")\n";
			ally = ally->next;
		}
		
		//Update Bullets
		for(int i = 0; i < numTurrets; i++)
		{
			if(turrets[i].isActive)
			{		
				turrets[i].fire(fmodSystem, sndFireGun, chTurrets);
				turrets[i].updateBullets();

				if(turrets[i].bullet.isActive)
				{					
					if(player->checkCollision(turrets[i].bullet.posX, turrets[i].bullet.posY, oENEMY))
					{
						fmodSystem->playSound(FMOD_CHANNEL_FREE, sndPlayerIsHit, false, &chEffects);
				
						playerHealth -= 25.0f;
						if(playerHealth == 0.0f)
							GameState = OVER;

						player->resetPos();

						// Remove Bullet
						turrets[i].bullet.isActive = false;
						turrets[i].bullet.posX = 2000.0f;
						turrets[i].bullet.posY = 2000.0f;
					}
				}
			}
		}

		enemy = enemies->first();

		while(enemy != NULL) 
		{
			if(player->checkCollision(enemy->posX, enemy->posY, oENEMY))
			{
					fmodSystem->playSound(FMOD_CHANNEL_FREE, sndPlayerIsHit, false, &chEffects);
				
					playerHealth -= 25.0f;
					if(playerHealth == 0.0f)
						GameState = OVER;

					player->resetPos();
			}
			enemy = enemy->next;
		}

		int idx = 0;
		ally = allies->first();
		while(ally != NULL) {
			if(player->checkCollision(ally->posX, ally->posY, oALLY)) {
					fmodSystem->playSound(FMOD_CHANNEL_FREE, sndAllyRescue, false, &chEffects);
	
					if(allies->removeCharAt(idx) == NULL)
						ally->setPos(2000.0f, 2000.0f);

					if(allies->cnt == 0)
						player->mKey = true;

					playerHealth += 50.0f;
					if(playerHealth > 100.0f && !cheater)
						playerHealth = 100.0f;
			}
			ally = ally->next;
			++idx;
		}

		if(player->posX > SCREEN_WIDTH || player->posX < 0 ||
		   player->posY > (SCREEN_HEIGHT - 60) || player->posY < 0) {	// height adjusted to account for HUD
			   if((ifWon || cheater) && (currentMap < NUMLVLS))
			   {
				   currentMap++; //If the player won, & this isn't the last level, move to next level & continue game.
				   ifWon = false; //Reset win condition

				   for(int i = 0; i < numTurrets; i++)
				   {
					   if(turrets[i].isActive)
						   turrets[i].isActive = false;
				   }

				   switch(currentMap)
				   {
				   case 1:
					copyMap((char*)&lvl1Map, (char*)&cMap);
					numTurrets = 0;
					break;
				   case 2:
					copyMap((char*)&lvl2Map, (char*)&cMap);
					numTurrets = 0;
					break;
				   case 3:
					copyMap((char*)&lvl3Map, (char*)&cMap);
					numTurrets = 1;
					break;
				   case 4:
					copyMap((char*)&lvl4Map, (char*)&cMap);
					numTurrets = 2;
					break;
				   case 5:
					copyMap((char*)&lvl5Map, (char*)&cMap);
					numTurrets = 3;
					break;
				   case 6:
					copyMap((char*)&lvl6Map, (char*)&cMap);
					numTurrets = 4;
					break;
				   case 7:
					copyMap((char*)&lvl7Map, (char*)&cMap);
					numTurrets = 5;
					break;
				   case 8:
					copyMap((char*)&lvl8Map, (char*)&cMap);
					numTurrets = 4;
					break;
				   case 9:
					copyMap((char*)&lvl9Map, (char*)&cMap);
					numTurrets = 6;
					break;
				   case 10:
					copyMap((char*)&lvl10Map, (char*)&cMap);
					numTurrets = 5;
					break;
				   case 11:
					copyMap((char*)&lvl11Map, (char*)&cMap);
					numTurrets = 7;
					break;
				   case 12:
					copyMap((char*)&lvl12Map, (char*)&cMap);
					numTurrets = 9;
					break;
				   case 13:
					copyMap((char*)&lvl13Map, (char*)&cMap);
					numTurrets = 4;
					break;
				   case 14:
					copyMap((char*)&lvl14Map, (char*)&cMap);
					numTurrets = 4;
					break;
				   case 15:
					copyMap((char*)&lvl15Map, (char*)&cMap);
					numTurrets = 6;
					break;
				   case 16:
					copyMap((char*)&lvl16Map, (char*)&cMap);
					numTurrets = 7;
					break;
				   case 17:
					copyMap((char*)&lvl17Map, (char*)&cMap);
					numTurrets = 8;
					break;
				   case 18:
					copyMap((char*)&lvl18Map, (char*)&cMap);
					numTurrets = 5;
					break;
				   case 19:
					copyMap((char*)&lvl19Map, (char*)&cMap);
					numTurrets = 3;
					break;
				   case 20:
					copyMap((char*)&lvl20Map, (char*)&cMap);
					numTurrets = 10;
					break;
				   }
				   //initCharLists();
			   }
			   else
				   GameState = OVER; //Otherwise either you've died or it's the end of the game.

			   renderFrame();
			   player->resetPos();
			   //enemy->resetPos();
			   //ally->resetPos();

			   enemy = enemies->first();
			   while(enemy != NULL) {
				   enemy->resetPos();
				   enemy = enemy->next;
			   }

			   ally = allies->first();
			   while(ally != NULL) {
				   ally->resetPos();
				   ally = ally->next;
			   }
		}
	}
}

// Renders a single frame
bool renderFrame()
{
	//GFX_LOG << "WinMain::renderFrame @ " << printTime() << "\tRender Frame Begins!\n";

	// Test Validity of GFX_BUFF (OffscreenPlain)
	if(GFX_BUFF == NULL) {
		//GFX_LOG << "ERROR!\tERROR!\tERROR!\n"
		//		<< "\t!!!!! Graphics Buffer Not Initialized !!!!!\n"
		//		<< "ERROR!\tERROR!\tERROR!\n";
			return false;
	}
	//GFX_LOG << "\tGFX_BUFF is VALID\n";
	
	// Clear out the buffers to a color
	d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
	//GFX_LOG << "\tBack Buffer Cleared!\n";

	// Begin our scene
	d3ddev->BeginScene();
	//GFX_LOG << "\tScene Started\n";

	IDirect3DSurface9* back = NULL;
	d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back);
	//GFX_LOG << /*"WinMain::renderFrame @ " << printTime() <<*/ "\tGot back buffer: " << back << "\n";


	std::stringstream HUDStr;
	std::string HUDBuff;

	//GFX_LOG << "\tGameState = ";
	switch(GameState)
	{
	case MENU:				//JJ What's Rendered at the Main Menu
		//GFX_LOG << "MENU\n";
		mainMenu();
		break;

	case GAME:				//JJ What's Rendered During Gameplay
		//GFX_LOG << "GAME\n";
		//JJ Render Map
		renderMap(back);

		//JJ Set Default Positions
		if(resetPos)
		{
			//GFX_LOG << "\t!!! Reset Player Positions !!!\n";
			player->setPos(player->defaultX, player->defaultY);
			//enemy->setPos(enemy->defaultX, enemy->defaultY);
			//ally->setPos(ally->defaultX, ally->defaultY);

			enemy = enemies->first();
			while(enemy != NULL) {
				enemy->setPos(enemy->defaultX, enemy->defaultY);
				enemy = enemy->next;
			}

			ally = allies->first();
			while(ally != NULL) {
				ally->setPos(ally->defaultX, ally->defaultY);
				ally = ally->next;
			}

			resetPos = false;
		}//END resetPos

		//JC Character Rendering
		renderChars(back);

		//JJ Render HUD
		renderHUD();

		break;

	case OVER:
		//JJ Display Game Over Menu Here
		overMenu();

		break;

	case CREDIT:
		//JJ Display Credits Here
		creditMenu();
		break;

	case HELP:	
		//JJ Display Help Menu Here
		helpMenu();
		break;

	case PAUSE:
		//JJ Display Pause Menu Here
		pauseMenu();
		break;

	case RESET:
		//JJ Actions for Resetting the Game
		d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
		break;

	case OPTIONS:
		//JJ Display Options Menu
		optionsMenu();
		break;

	case QUIT:			
		//JJ Nothing is Rendered Here, the Game Has Ended
		PostQuitMessage(0);
		break;
	} // END switch(GameState)
	
	// End our scene
	d3ddev->EndScene();

	// Display the scen
	d3ddev->Present(NULL, NULL, NULL, NULL);
	return true;
}

//JJ Main Menu Setup
void mainMenu(void)
{
	//JJ Declare and resize a RECT for the main window
	RECT rect;
	GetWindowRect(hWnd, &rect);
	rect.right = rect.right - rect.left;
	rect.bottom = rect.bottom - rect.top;
	rect.left = 0;
	rect.top = 0;

	//JJ String to hold the menu text
	std::string MenuString;

	//JJ Print the title
	MenuString = "\n\nESCAPE FROM AREA 52!";
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

	//JJ Print the Start Button
	MenuString = "\n\n\n\n\n\nPress Enter to Start Game \n\n\n\n Press H for Help";
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

	//JJ Print the Credits Option
	MenuString = "\n\n\n\n\n\n\n\nPress O for Options\n\n\n\nPress C for Credits\n\n\n\nPress Q to Exit Game";
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));
}

//JJ Options Menu Setup
void optionsMenu(void)
{
	//JJ Declare and resize a RECT for the main window
	RECT rect;
	GetWindowRect(hWnd, &rect);
	rect.right = rect.right - rect.left;
	rect.bottom = rect.bottom - rect.top;
	rect.left = 0;
	rect.top = 0;

	//JJ String to hold the menu text
	std::string MenuString;
	std::stringstream tempStr;
	bool mute = false;
	bool sM = false;
	bool mM = false;
	bool tM = false;

	int vol = (int)(sndVolume * 100);
	float vol1;

	chEffects->getVolume(&vol1);

	vol1 = vol1 * 100;
	//JJ Print the title
	tempStr << "\n\nOPTIONS";

	//JJ Print +/- options
	tempStr << "\n\n\nPress + or - to raise/lower\nsound volume:      ";
	switch(vol)
	{
	case 0:
		tempStr << "Mute";
		break;
	case 25:
		tempStr << "Low";
		break;
	case 50:
		tempStr << "Medium";
		break;
	case 75:
		tempStr << "High";
		break;
	case 100:
		tempStr << "Max";
		break;
	}

	//JJ Print Mute options
	tempStr << "\n\n\nPress M or U to Mute/Unmute\n sound volume:      ";
	
	chEffects->getMute(&sM);
	chMusic->getMute(&mM);
	chTurrets->getMute(&tM);

	if(sM || mM || tM)
		mute = true;
	else
		mute = false;


	if(mute)
		tempStr << "Muted";
	else if(!mute)
		tempStr << "Unmuted";

	//JJ Print Back button
	tempStr << "\n\n\n\nPress Backspace to return\nto the Main Menu.";

	MenuString = tempStr.str();
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));
}

//JJ Pause Menu Setup
void pauseMenu(void)
{
	//JJ Declare and resize a RECT for the main window
	RECT rect;
	GetWindowRect(hWnd, &rect);
	rect.right = rect.right - rect.left;
	rect.bottom = rect.bottom - rect.top;
	rect.left = 0;
	rect.top = 0;

	//JJ String to hold the menu text
	std::string MenuString;

	//JJ Print the title
	MenuString = "\n\nGame Paused";
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

	//JJ Print the Start Button
	MenuString = "\n\n\n\n\n\nPress Enter to Resume \n\n\n\n Press H for Help Guide \n\n\n\n Press Backspace\n to return to Main Menu";
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

	if(cheater)
	{
		MenuString = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nCheats are enabled!";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 0, 0));
	}
}

void overMenu(void)
{
	//JJ Declare and resize a RECT for the main window
	RECT rect;
	GetWindowRect(hWnd, &rect);
	rect.right = rect.right - rect.left;
	rect.bottom = rect.bottom - rect.top;
	rect.left = 0;
	rect.top = 0;

	//JJ String to hold the menu text
	std::string MenuString;

	switch (ifWon)
	{
	case false:
		//JJ Print the title
		MenuString = "\n\nGAME OVER!";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

		//JJ Print the Start Button
		MenuString = "\n\n\n\n\n\nPress Space to restart the game \n\n\n\n Press Backspace to\n return to the Main Menu";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));
		break;
	case true:
		//JJ Print the title
		MenuString = "\n\nCONGRATULATIONS\nYou Won!";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

		//JJ Print the Start Button
		MenuString = "\n\n\n\n\n\nPress Space to restart the game \n\n\n\n Press Backspace to\n return to the Main Menu";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));
		break;
	}
}

void helpMenu(void)
{
	//JJ Declare and resize a RECT for the main window
	RECT rect;
	GetWindowRect(hWnd, &rect);
	rect.right = rect.right - rect.left;
	rect.bottom = rect.bottom - rect.top;
	rect.left = 0;
	rect.top = 0;

	//JJ String to hold the menu text
	std::string MenuString;

	//JJ Render Based on Page
	switch(helpPageNum)
	{
	case 0:
		//JJ Print the title
		MenuString = "\nPLAYER HELP GUIDE";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

		//JJ Print Player Guide
		MenuString = "\n\n\nMovement: Arrow keys\n\nEnemies: Damage you on contact";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 0, 255, 255));

		//JJ Print Player Guide
		MenuString = "\n\n\n\n\n\n\nAllies: Restore health on contact &\ngives master key once all are rescued\n\nKeys: Unlocks doors.\nWhen a door unlocks, key is lost";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 0, 255, 255));

		//JJ Print Player Guide
		MenuString = "\n\n\n\n\n\n\n\n\n\n\n\n\nPress Right or Left Arrow\nto Scroll Pages";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

		//JJ Print Player Guide
		if(lastState == PAUSE)
			MenuString = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nPress Backspace\nto Resume Game";
		else
			MenuString = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nPress Backspace\nto Return to Main Menu";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));
		break;

	case 1:
		//JJ Print the title
		MenuString = "\nPLAYER HELP GUIDE";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

		//JJ Print Player Guide
		MenuString = "\n\n\nDoors: Requires key to unlock\n\nMaster Door: Advance to the \nnext level. Can only be accessed";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 0, 255, 255));

		//JJ Print Player Guide
		MenuString = "\n\n\n\n\n\n\nby getting the master key\nfrom allies.\n\nTurrets: Fires bullets constantly.\nBullets damage you on contact";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 0, 255, 255));

		//JJ Print Player Guide
		MenuString = "\n\n\n\n\n\n\n\n\n\n\n\n\nPress Right or Left Arrow\nto Scroll Pages";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

		//JJ Print Player Guide
		if(lastState == PAUSE)
			MenuString = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nPress Backspace\nto Resume Game";
		else
			MenuString = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nPress Backspace\nto Return to Main Menu";
		m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));
		break;
	}
}

void creditMenu(void)
{
	//JJ Declare and resize a RECT for the main window
	RECT rect;
	GetWindowRect(hWnd, &rect);
	rect.right = rect.right - rect.left;
	rect.bottom = rect.bottom - rect.top;
	rect.left = 0;
	rect.top = 0;

	//JJ String to hold the menu text
	std::string MenuString;

	//JJ Print the title
	MenuString = "\n\nCREDITS";
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

	//JJ Print the Start Button
	MenuString = "\n\n\n\n\nDeVry University's\nSenior Project II - Team A:\n\n Joshua Cripe & Justin Jacques";
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));

	//JJ Main Menu Option
	MenuString = "\n\n\n\n\n\n\n\n\n\n\n\n\n Press Backspace for the Main Menu";
	m_pD3DFont->DrawTextA(0, (LPCSTR)MenuString.c_str(), -1, &rect, DT_CENTER | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));
}

void renderHUD(void)
{
	//JJ Render HUD //
			
	// Calculate RECT structure for text drawing placement, using whole screen
	RECT rect;
	GetClientRect (hWnd, &rect);
	rect.right = rect.right - rect.left;
	rect.bottom = rect.bottom - rect.top;
	rect.left = 0;
	rect.top = 405;

	// Draw HUD Values
	std::stringstream HUDStr1;
	HUDStr1 << "\n\nLevel: " << currentMap;
	std::string HUDBuff1 = HUDStr1.str();
	m_pD3DFont1->DrawTextA(0, (LPCSTR)HUDBuff1.c_str(), -1, &rect, DT_CENTER | DT_CENTER, D3DCOLOR_XRGB(255, 0, 0));

	std::stringstream HUDStr;
	HUDStr << " Health: " << playerHealth << "   Keys: " << player->nKeys;
	if(cheater)
		HUDStr << "   CHEATER!";
	else if(player->mKey)
		HUDStr << "   Master Key!";

	std::string HUDBuff = HUDStr.str();
	m_pD3DFont->DrawTextA(0, (LPCSTR)HUDBuff.c_str(), -1, &rect, DT_BOTTOM | DT_LEFT, D3DCOLOR_XRGB(255, 0, 0));
}

void reset(void)
{
	//JJ A Function That Resets the Game to Default Status
	currentMap = 1;
	copyMap((char*)&lvl1Map, (char*)&cMap);
	playerHealth = 100.0f;
	hasKeyCard = false;
	player->nKeys = 0;
	numTurrets = 0;

	resetPos = true;

	GameState = GAME;
}

void copyMap(char* orig, char* dest) {
	for(int i = 0; i < (ROWMAX * COLMAX); ++i)
		*dest++ = *orig++;

	initCharLists();
}

//JC Moved here from "renderFrame()...case GAME:" for easier code management
void renderMap(IDirect3DSurface9* back) {
	RECT srcRec, desRec;

	//JJ Loop through map, select the right sprite, and render
	mapSprite.pX = mapSprite.pY = 0;

	for(int i = 0; i < ROWMAX; i++)
	{
		for(int j = 0; j < COLMAX; j++)
		{
			char mapTile = cMap[i][j];//lvl1Map[i][j];
				
			if(mapTile == 'P' || mapTile == 'E' || mapTile == 'F')
			{
				// Draw the floor sprite
				if(currentMap > 0 && currentMap < 6)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 4;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 3;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 6;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 3;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 7;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 3;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 8;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 3;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
					
				if(mapTile == 'P')
				{ player->defaultX = mapSprite.pX; player->defaultY = mapSprite.pY; }


				srcRec = mapSprite.sourceRect;
				desRec.left = (long)mapSprite.pX; desRec.right = (long)(mapSprite.pX + SPRITE_SIZE);
				desRec.top = (long)mapSprite.pY; desRec.bottom = (long)(mapSprite.pY + SPRITE_SIZE);

				//Draw Sprite
				d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);

			} // END P, E, F Rules

			if(mapTile == 'A' || mapTile == 'B' || mapTile == 'C')
			{
				//Set the appropriate sprite (Wall in this case)
				if(currentMap > 0 && currentMap < 6)
				{
					switch(mapTile)
					{
					case 'A':
						mapSprite.sourceRect.top = SPRITE_SIZE * 4; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 0; // First sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					case 'B':
						mapSprite.sourceRect.top = SPRITE_SIZE * 4; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 1; // Second Sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					case 'C':
						mapSprite.sourceRect.top = SPRITE_SIZE * 4; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 2; // Third Sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					}
				}
				else if(currentMap > 5 && currentMap < 11)
				{
					switch(mapTile)
					{
					case 'A':
						mapSprite.sourceRect.top = SPRITE_SIZE * 6; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 0; // First sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					case 'B':
						mapSprite.sourceRect.top = SPRITE_SIZE * 6; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 1; // Second Sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					case 'C':
						mapSprite.sourceRect.top = SPRITE_SIZE * 6; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 2; // Third Sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					}
				}
				else if(currentMap > 10 && currentMap < 16)
				{
					switch(mapTile)
					{
					case 'A':
						mapSprite.sourceRect.top = SPRITE_SIZE * 7; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 0; // First sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					case 'B':
						mapSprite.sourceRect.top = SPRITE_SIZE * 7; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 1; // Second Sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					case 'C':
						mapSprite.sourceRect.top = SPRITE_SIZE * 7; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 2; // Third Sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					}
				}
				else if(currentMap > 15 && currentMap < 21)
				{
					switch(mapTile)
					{
					case 'A':
						mapSprite.sourceRect.top = SPRITE_SIZE * 8; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 0; // First sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					case 'B':
						mapSprite.sourceRect.top = SPRITE_SIZE * 8; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 1; // Second Sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					case 'C':
						mapSprite.sourceRect.top = SPRITE_SIZE * 8; // Update '1' to appropriate row of map sprites
						mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
						mapSprite.sourceRect.left = SPRITE_SIZE * 2; // Third Sprite
						mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						break;
					}
				}

				srcRec = mapSprite.sourceRect;
					
				desRec.left = (long)mapSprite.pX; desRec.right = (long)(mapSprite.pX + SPRITE_SIZE);
				desRec.top = (long)mapSprite.pY; desRec.bottom = (long)(mapSprite.pY + SPRITE_SIZE);

				//Draw Sprite
				d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);

				// Collision check
				player->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);

				enemy = enemies->first();
				while(enemy != NULL) {
					enemy->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					enemy = enemy->next;
				}

				ally = allies->first();
				while(ally != NULL) {
					ally->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					ally = ally->next;
				}

				// Check Bullet Collisions
				for(int iT = 0; iT < numTurrets; iT++)
				{
					if(turrets[iT].isActive)
					{
						if(turrets[iT].bullet.isActive)
						{
							if(turrets[iT].bullet.checkCollision(mapSprite.pX, mapSprite.pY, oWALL))
							{
								turrets[iT].bullet.isActive = false;
								turrets[iT].bullet.posX = 1000.0f;
								turrets[iT].bullet.posY = 1000.0f;
							}
						}
					}
				}
			} // END WALLS

			else if(mapTile == 'K')
			{
				//Set the appropriate sprite (keycard in this case)
				if(currentMap > 0 && currentMap < 6)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 5;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 0;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 6;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 5;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 7;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 5;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 8;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 5;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}					

				srcRec = mapSprite.sourceRect;
				desRec.left = (long)mapSprite.pX; desRec.right = (long)(mapSprite.pX + SPRITE_SIZE);
				desRec.top = (long)mapSprite.pY; desRec.bottom = (long)(mapSprite.pY + SPRITE_SIZE);

				if(player->checkCollision(mapSprite.pX, mapSprite.pY, oKEY)) {
					player->pickupKey();
					fmodSystem->playSound(FMOD_CHANNEL_FREE, sndPickup, false, &chEffects);
					cMap[i][j] = ' ';
				} else
					d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);
			} // END KEYS

			if(mapTile == 'D')
			{
				//Set the appropriate sprite (door in this case)
				if(currentMap > 0 && currentMap < 6)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 5;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 1;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 6;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 6;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 7;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 6;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 8;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 6;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
					
				srcRec = mapSprite.sourceRect;
				desRec.left = (long)mapSprite.pX; desRec.right = (long)(mapSprite.pX + SPRITE_SIZE);
				desRec.top = (long)mapSprite.pY; desRec.bottom = (long)(mapSprite.pY + SPRITE_SIZE);
				//Draw Sprite
				d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);

				// Collision check
				if(player->checkCollision(mapSprite.pX, mapSprite.pY, oLDOOR))
				{
					if(player->nKeys > 0)
					{
						//Player is at the door, with a keycard.
						//Draw door open & remove keycard.
						//Set the appropriate sprite
						if(currentMap > 0 && currentMap < 6)
						{
							mapSprite.sourceRect.top = SPRITE_SIZE * 5;
							mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
							mapSprite.sourceRect.left = SPRITE_SIZE * 2;
							mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						}
						else if(currentMap > 5 && currentMap < 11)
						{
							mapSprite.sourceRect.top = SPRITE_SIZE * 6;
							mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
							mapSprite.sourceRect.left = SPRITE_SIZE * 7;
							mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						}
						else if(currentMap > 10 && currentMap < 16)
						{
							mapSprite.sourceRect.top = SPRITE_SIZE * 7;
							mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
							mapSprite.sourceRect.left = SPRITE_SIZE * 7;
							mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						}
						else if(currentMap > 15 && currentMap < 21)
						{
							mapSprite.sourceRect.top = SPRITE_SIZE * 8;
							mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
							mapSprite.sourceRect.left = SPRITE_SIZE * 7;
							mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						}
							
						srcRec = mapSprite.sourceRect;
						cMap[i][j] = 'd';
						player->nKeys -= 1;

						fmodSystem->playSound(FMOD_CHANNEL_FREE, sndDoorOpen, false, &chEffects);
					} // END Key Check
				} // END player->checkCollision
					
				//enemy->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
				//ally->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
				enemy = enemies->first();
				while(enemy != NULL) {
					enemy->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					enemy = enemy->next;
				}

				ally = allies->first();
				while(ally != NULL) {
					ally->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					ally = ally->next;
				}

				// Check Bullet Collisions
				for(int iT = 0; iT < numTurrets; iT++)
				{
					if(turrets[iT].isActive)
					{
						if(turrets[iT].bullet.isActive)
						{
							if(turrets[iT].bullet.checkCollision(mapSprite.pX, mapSprite.pY, oWALL))
							{
								turrets[iT].bullet.isActive = false;
								turrets[iT].bullet.posX = 1000.0f;
								turrets[iT].bullet.posY = 1000.0f;
							}
						}
					}
				}
			} // END LOCKED DOORS

			if(mapTile == 'd')
			{
				//Set the appropriate sprite
				if(currentMap > 0 && currentMap < 6)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 5;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 2;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 6;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 7;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 7;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 7;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 8;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 7;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}

				srcRec = mapSprite.sourceRect;
				desRec.left = (long)mapSprite.pX; desRec.right = (long)(mapSprite.pX + SPRITE_SIZE);
				desRec.top = (long)mapSprite.pY; desRec.bottom = (long)(mapSprite.pY + SPRITE_SIZE);

				//Draw Sprite
				d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);

				//Collision Checking (Block NPCs)
				//enemy->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
				//ally->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
				enemy = enemies->first();
				while(enemy != NULL) {
					enemy->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					enemy = enemy->next;
				}

				ally = allies->first();
				while(ally != NULL) {
					ally->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					ally = ally->next;
				}

				// Check Bullet Collisions
				for(int iT = 0; iT < numTurrets; iT++)
				{
					if(turrets[iT].isActive)
					{
						if(turrets[iT].bullet.isActive)
						{
							if(turrets[iT].bullet.checkCollision(mapSprite.pX, mapSprite.pY, oWALL))
							{
								turrets[iT].bullet.isActive = false;
								turrets[iT].bullet.posX = 1000.0f;
								turrets[iT].bullet.posY = 1000.0f;
							}
						}
					}
				}
			} // END UNLOCKED DOORS

			//JC Added render code for Master Door
			if(mapTile == 'Z') // Master Door
			{
				// Set the appropriate sprite
				if(currentMap > 0 && currentMap < 6)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 5;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 7;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 5;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 7;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 5;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 7;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 5;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 7;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
					
				// Calculate Destination Rectangle
				srcRec = mapSprite.sourceRect;
				desRec.left = (long)mapSprite.pX; desRec.right = (long)(mapSprite.pX + SPRITE_SIZE);
				desRec.top = (long)mapSprite.pY; desRec.bottom = (long)(mapSprite.pY + SPRITE_SIZE);

				//Draw Sprite
				d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);

				//Collision Detection
				//enemy->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
				//ally->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
				enemy = enemies->first();
				while(enemy != NULL) {
					enemy->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					enemy = enemy->next;
				}

				ally = allies->first();
				while(ally != NULL) {
					ally->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					ally = ally->next;
				}

				// Check Bullet Collisions
				for(int iT = 0; iT < numTurrets; iT++)
				{
					if(turrets[iT].isActive)
					{
						if(turrets[iT].bullet.isActive)
						{
							if(turrets[iT].bullet.checkCollision(mapSprite.pX, mapSprite.pY, oWALL))
							{
								turrets[iT].bullet.isActive = false;
								turrets[iT].bullet.posX = 1000.0f;
								turrets[iT].bullet.posY = 1000.0f;
							}
						}
					}
				}

				// Collision check
				if(player->checkCollision(mapSprite.pX, mapSprite.pY, oLDOOR))
				{
					if(player->mKey == true)
					{
						//Player is at the door, with a keycard.
						//Draw door open & remove keycard.
						//Set the appropriate sprite
						if(currentMap > 0 && currentMap < 6)
						{
							mapSprite.sourceRect.top = SPRITE_SIZE * 5;
							mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
							mapSprite.sourceRect.left = SPRITE_SIZE * 2;
							mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						}
						else if(currentMap > 5 && currentMap < 11)
						{
							mapSprite.sourceRect.top = SPRITE_SIZE * 6;
							mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
							mapSprite.sourceRect.left = SPRITE_SIZE * 7;
							mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						}
						else if(currentMap > 10 && currentMap < 16)
						{
							mapSprite.sourceRect.top = SPRITE_SIZE * 7;
							mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
							mapSprite.sourceRect.left = SPRITE_SIZE * 7;
							mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						}
						else if(currentMap > 15 && currentMap < 21)
						{
							mapSprite.sourceRect.top = SPRITE_SIZE * 8;
							mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
							mapSprite.sourceRect.left = SPRITE_SIZE * 7;
							mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
						}

						srcRec = mapSprite.sourceRect;
						cMap[i][j] = 'd';
						player->mKey = false;

						//JJ set ifWon to true cause the level is complete
						ifWon = true;

						fmodSystem->playSound(FMOD_CHANNEL_FREE, sndDoorOpen, false, &chEffects);
					} // END Key Check
				} // END player->checkCollision
			}

			if(mapTile == ' ') //Floors
			{
				//Set the appropriate sprite
				if(currentMap > 0 && currentMap < 6)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 4;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 3;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 6;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 3;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 7;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 3;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 8;
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 3;
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}

				srcRec = mapSprite.sourceRect;
				desRec.left = (long)mapSprite.pX; desRec.right = (long)(mapSprite.pX + SPRITE_SIZE);
				desRec.top = (long)mapSprite.pY; desRec.bottom = (long)(mapSprite.pY + SPRITE_SIZE);

				//Draw Sprite
				d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);
			} // END FLOORS

			if(mapTile == '1' || mapTile == '2' || mapTile == '3' || mapTile == '4')
			{
				//Set the appropriate sprite (Turret in this case)
				if(currentMap > 0 && currentMap < 6)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 4; // Update '1' to appropriate row of map sprites
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 4; // Fourth sprite
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 6; // Update '1' to appropriate row of map sprites
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 4; // Fourth sprite
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 7; // Update '1' to appropriate row of map sprites
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 4; // Fourth sprite
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)
				{
					mapSprite.sourceRect.top = SPRITE_SIZE * 8; // Update '1' to appropriate row of map sprites
					mapSprite.sourceRect.bottom = mapSprite.sourceRect.top + SPRITE_SIZE;
					mapSprite.sourceRect.left = SPRITE_SIZE * 4; // Fourth sprite
					mapSprite.sourceRect.right = mapSprite.sourceRect.left + SPRITE_SIZE;
				}
					
				srcRec = mapSprite.sourceRect;
					
				desRec.left = (long)mapSprite.pX; desRec.right = (long)(mapSprite.pX + SPRITE_SIZE);
				desRec.top = (long)mapSprite.pY; desRec.bottom = (long)(mapSprite.pY + SPRITE_SIZE);

				//Draw Sprite
				d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);					

				//Find the next inactive turret
				for(int iT = 0; iT < numTurrets; iT++)
				{
					if(!turrets[iT].isActive)
					{	//Set Turret Position & Direction
						turrets[iT].isActive = true;

						turrets[iT].posX = mapSprite.pX;
						turrets[iT].posY = mapSprite.pY;
							
						turrets[iT].bullet.posX = mapSprite.pX;
						turrets[iT].bullet.posY = mapSprite.pY;
						
						turrets[iT].dir  = mapTile - 48;  // Sets the dir to the correct int (i.e. 49(ASCII for 1) - 48 = 1)

						//End Loop
						break;
					}
				}
					
				// Collision check
				player->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);

				enemy = enemies->first();
				while(enemy != NULL) {
					enemy->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					enemy = enemy->next;
				}

				ally = allies->first();
				while(ally != NULL) {
					ally->checkCollision(mapSprite.pX, mapSprite.pY, oWALL);
					ally = ally->next;
				}
			} // END TURRETS

			// Increment Column Position
			mapSprite.pX += SPRITE_SIZE;
		} // END j - Column Counter
			
		// Reset Column Position
		mapSprite.pX = 0;

		// Increment Row Position
		mapSprite.pY += SPRITE_SIZE;
	} // END i - Row Counter
}

void renderChars(IDirect3DSurface9* back) {
	RECT srcRec, desRec;
	float x, y;

	//JC Cycle Frames
	if(frameCount >= FRAME_RATE) {
		player->cycleFrame();
		
		//enemy->cycleFrame();
		enemy = enemies->first();
		while(enemy != NULL) {
			enemy->cycleFrame();
			enemy = enemy->next;
		}

		//ally->cycleFrame();
		ally = allies->first();
		while(ally != NULL) {
			ally->cycleFrame();
			ally = ally->next;
		}

		frameCount = 0;
	}

	//JC RENDER PLAYER
	srcRec = player->getSourceRect();
	player->getPos(&x, &y);
	desRec.left = (long)x; desRec.right = (long)(x + SPRITE_SIZE);
	desRec.top = (long)y; desRec.bottom = (long)(y + SPRITE_SIZE);
	d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);

	//JC Added for Alpha Capable Sprites
	D3DXVECTOR3 vecPos = D3DXVECTOR3(x, y, 0);
	D3DXVECTOR3 vecCen = D3DXVECTOR3((SPRITE_SIZE/2), (SPRITE_SIZE/2), 0);

	if (AlphaSprite && AlphaTexture)
	{
		srcRec.right += 5;
		srcRec.bottom += 5;
		AlphaSprite->Begin( D3DXSPRITE_ALPHABLEND );
		//AlphaSprite->Draw(AlphaTexture, &srcRec, NULL, &vecPos, 0xffffffff);
		AlphaSprite->End();
	}

	//JC RENDER ENEMY
	enemy = enemies->first();
	while(enemy != NULL) {
		srcRec = enemy->getSourceRect();
		enemy->getPos(&x, &y);
		desRec.left = (long)x; desRec.right = (long)(x + SPRITE_SIZE);
		desRec.top = (long)y; desRec.bottom = (long)(y + SPRITE_SIZE);
		d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);
		enemy = enemy->next;
	}

	//JC RENDER ALLY
	ally = allies->first();
	while(ally != NULL) {
		srcRec = ally->getSourceRect();
		ally->getPos(&x, &y);
		desRec.left = (long)x; desRec.right = (long)(x + SPRITE_SIZE);
		desRec.top = (long)y; desRec.bottom = (long)(y + SPRITE_SIZE);
		d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);
		ally = ally->next;
	}

	//JJ RENDER BULLETS
	for(int i = 0; i < numTurrets; i++)
	{
		if(turrets[i].bullet.isActive)
		{
			switch(turrets[i].dir)	// Check Direction
			{
			case 1: // Up
				if(currentMap > 0 && currentMap < 6)	// First Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 5;
					srcRec.left = SPRITE_SIZE * 4;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)	// Second Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 9;
					srcRec.left = SPRITE_SIZE * 1;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)	// Third Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 10;
					srcRec.left = SPRITE_SIZE * 1;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)	// Fourth Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 11;
					srcRec.left = SPRITE_SIZE * 1;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				break;
			case 2: // Left
				if(currentMap > 0 && currentMap < 6)	// First Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 5;
					srcRec.left = SPRITE_SIZE * 3;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)	// Second Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 9;
					srcRec.left = SPRITE_SIZE * 0;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)	// Third Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 10;
					srcRec.left = SPRITE_SIZE * 0;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)	// Fourth Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 11;
					srcRec.left = SPRITE_SIZE * 0;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				break;
			case 3: // Right
				if(currentMap > 0 && currentMap < 6)	// First Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 5;
					srcRec.left = SPRITE_SIZE * 5;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)	// Second Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 9;
					srcRec.left = SPRITE_SIZE * 2;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)	// Third Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 10;
					srcRec.left = SPRITE_SIZE * 2;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)	// Fourth Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 11;
					srcRec.left = SPRITE_SIZE * 2;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				break;
			case 4: // Down
				if(currentMap > 0 && currentMap < 6)	// First Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 5;
					srcRec.left = SPRITE_SIZE * 6;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 5 && currentMap < 11)	// Second Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 9;
					srcRec.left = SPRITE_SIZE * 3;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 10 && currentMap < 16)	// Third Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 10;
					srcRec.left = SPRITE_SIZE * 3;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				else if(currentMap > 15 && currentMap < 21)	// Fourth Lvl Set
				{
					srcRec.top = SPRITE_SIZE * 11;
					srcRec.left = SPRITE_SIZE * 3;
					srcRec.bottom = srcRec.top + SPRITE_SIZE;
					srcRec.right = srcRec.left + SPRITE_SIZE;
				}
				break;
			}
				
			x = turrets[i].bullet.posX;
			y = turrets[i].bullet.posY;

			desRec.left = (long)x; desRec.right = (long)(x + SPRITE_SIZE);
			desRec.top = (long)y; desRec.bottom = (long)(y + SPRITE_SIZE);

			d3ddev->StretchRect(GFX_BUFF, &srcRec, back, &desRec, D3DTEXF_NONE);
		}
	}
}

// CHARACTER INITIALIZATION
void initPlayer(void) {
	player = new Character((SPRITE_SIZE * 2), (SPRITE_SIZE * 2), cPLAYER);
	//player->setPos(21, 21); //((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2));
	player->setVel(0, 0);
	player->sprite.cFrame = 0;
	player->sprite.nFrames = 4;
	player->log = &PLY_LOG;
}

Character* initEnemy(float x, float y) {
	//enemy = new Character(21, (SCREEN_HEIGHT - 100), cENEMY);
	enemy = new Character(x, y, cENEMY);
	enemy->setVel(1, -1);
	enemy->sprite.cFrame = 0;
	enemy->sprite.nFrames = 4;
	enemy->log = &ENM_LOG;
	return enemy;
}

Character* initAlly(float x, float y) {
	//ally = new Character((SCREEN_WIDTH - 60), 21, cALLY);
	ally = new Character(x, y, cALLY);
	ally->setVel(-1, 1);
	ally->sprite.cFrame = 0;
	ally->sprite.nFrames = 4;
	ally->log = &ALY_LOG;
	return ally;
}

void initCharLists(void) {
	GFX_LOG << "WinMain::initCharLists() START @ " << printTime();
	allies = new CharacterList();
	enemies = new CharacterList();

	for(int i = 0; i < ROWMAX; ++i) {
		for(int j = 0; j < COLMAX; ++j) {
			char mapTile = cMap[i][j];
			float x = (float)(j * SPRITE_SIZE);
			float y = (float)(i * SPRITE_SIZE);

			if(mapTile == 'E')
			{
				GFX_LOG << "\tENEMY (" << x << ", " << y << ")\n";
				enemies->addChar(initEnemy(x, y));
			}

			if(mapTile == 'F')
			{
				GFX_LOG << "\tALLY (" << x << ", " << y << ")\n";
				allies->addChar(initAlly(x, y));
			}
		}
	}
	numAllies = allies->cnt;
	GFX_LOG << "WinMain::initCharLists() STOP @ " << printTime();
}

//JC Added for main log
bool initLogs( void ) {
	if(!initMainLog())
		return false;
	if(!initGFXLog())
		return false;
	if(!initPlayerLog())
		return false;
	if(!initEnemyLog())
		return false;
	if(!initAllyLog())
		return false;
	return true;
}

bool initMainLog(const char* logFile) {
	logFile = logFile == NULL ? "logs\\Main.log" : logFile;
	LOG.open(logFile);
	if(LOG.is_open() && LOG.good()) {
		//LOG << "Main Log Initialized @ " << printTime();
		LOG.flush();
		return true;
	}
	return false;
}

void closeLogs(void) {
	if(LOG != NULL)
		closeMainLog();
	if(GFX_LOG != NULL)
		closeGFXLog();
	if(PLY_LOG != NULL)
		closePlayerLog();
	if(ENM_LOG != NULL)
		closeEnemyLog();
	if(ALY_LOG != NULL)
		closeAllyLog();
}

void closeMainLog( void ) {
	//LOG << "Main Log Closed @ " << printTime();
	LOG.flush();
	LOG.close();
}

bool initPlayerLog(const char* logFile) {
	logFile = logFile == NULL ? "logs\\Player.log" : logFile;
	PLY_LOG.open(logFile);
	if(PLY_LOG.is_open() && PLY_LOG.good()) {
		//PLY_LOG << "Player Log Initialized @ " << printTime();
		PLY_LOG.flush();
		return true;
	}
	return false;
}

void closePlayerLog( void ) {
	//PLY_LOG << "Player Log Closed @ " << printTime();
	PLY_LOG.flush();
	PLY_LOG.close();
}

bool initEnemyLog(const char* logFile) {
	logFile = logFile == NULL ? "logs\\Enemy.log" : logFile;
	ENM_LOG.open(logFile);
	if(ENM_LOG.is_open() && ENM_LOG.good()) {
		//ENM_LOG << "Enemy Log Initialized @ " << printTime();
		//ENM_LOG.flush();
		return true;
	}
	return false;
}

void closeEnemyLog( void ) {
	//ENM_LOG << "Enemy Log Closed @ " << printTime();
	ENM_LOG.flush();
	ENM_LOG.close();
}

bool initAllyLog(const char* logFile) {
	logFile = logFile == NULL ? "logs\\Ally.log" : logFile;
	ALY_LOG.open(logFile);
	if(ALY_LOG.is_open() && ALY_LOG.good()) {
		//ALY_LOG << "Ally Log Initialized @ " << printTime();
		//ALY_LOG.flush();
		return true;
	}
	return false;
}

void closeAllyLog( void ) {
	//ALY_LOG << "Ally Log Closed @ " << printTime();
	ALY_LOG.flush();
	ALY_LOG.close();
}